// Copyright (c) 2007, Brian Duff

// See LICENSE for full license details.

package org.dubh.jdant;

import java.net.URL;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

/**
 * A content set is a collection of paths and include / exclude filters
 * stored in a JDeveloper project file.
 *
 * @author brian.duff@dubh.org
 */
public final class ContentSet
{
  private static final String KEY_JAVA = "oracle.jdeveloper.model.PathsConfiguration/javaContentSet";
  
  private final List<URL> _paths;
  private final List<String> _patternFilters;
  
  ContentSet( ROHashStructure hs )
  {
    if ( hs == null ) throw new NullPointerException ( "hs is null" );
    
    _paths = convert( hs.getListStructure( "url-path" ), URL.class );
    _patternFilters = convert( hs.getListStructure( "pattern-filters" ), String.class );
  }

  /**
   * Finds the java content set in the given project.
   * 
   * @param projectFile a project to search for the java content set.
   * @return the java content set.
   */
  public static ContentSet findJavaContentSet( ProjectFile projectFile )
  {
    return getInstance( projectFile, KEY_JAVA );
  }
  
  private static ContentSet getInstance( ProjectFile projectFile, String key )
  {
    return new ContentSet( projectFile.hashStructure().getHashStructure( key ) );
  }
  
  // Note: Incorrect "unused" warning on this method in JDev 11g.
  private <T> List<T> convert( List<?> l, Class<T> type ) 
  {
    if ( l == null ) return Collections.emptyList();
    
    List<T> result = new ArrayList<T>();
    for ( Object o : l )
    {
      if ( type.isInstance( o ) ) result.add( type.cast( o ) );
    }
    return result;
  }
  
  /**
   * Returns the list of paths for this content set.
   * 
   * @return the list of paths for this content set. Never returns null. The
   *    returned list is unmodifiable.
   */
  public List<URL> paths() 
  {
    return Collections.unmodifiableList( _paths );
  }
  
  /**
   * Returns the list of patterns for this content set. Never returns null.
   * 
   * @return the list of pattern filters for this content set. Never returns
   *    null. The list collection is unmodifiable.
   */
  public List<String> patternFilters()
  {
    return Collections.unmodifiableList( _patternFilters );
  }
  
  /**
   * Gets the subset of {@link #patternFilters()} which are include rules.
   * 
   * @return include rules.
   */
  public List<String> includedPatterns()
  {
    return patternsStartingWith( '+' );
  }
  
  /**
   * Gets the subset of {@link #patternFilters()} which are exclude rules.
   * 
   * @return exclude rules.
   */
  public List<String> excludedPatterns()
  {
    return patternsStartingWith( '-' );
  }
  
  
  private List<String> patternsStartingWith( char c )
  {
    List<String> matching = new ArrayList<String>();
    
    for ( String pattern : patternFilters() )
    {
      if ( pattern.length() > 0 && pattern.charAt( 0 ) == c )
      {
        matching.add( pattern.substring( 1 ) );
      }
    }
    
    return Collections.unmodifiableList( matching );
  }
  
  /**
   * Converts a pattern list to a string by comma separating each item in the
   * list.
   * 
   * @param patterns a collection of patterns.
   * @return a comma separated list of patterns.
   */
  public static String patternListToString( Collection<String> patterns )
  {
    return Strings.collectionToString( patterns, ',' );
  }
}
